<?php

declare(strict_types=1);

namespace App\Middleware;

use App\Constants\HttpStatus;
use App\Event\Exceptions;
use App\Exception\DbException;
use App\Exception\ValidatorException;
use App\Service\OtherQueueService;
use App\Service\QueueService;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\HttpServer\Response;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\HttpServer\Contract\RequestInterface;


class ResponseMiddleware implements MiddlewareInterface
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    /**
     * @var HttpResponse
     */
    protected $response;

    /**
     * @var RequestInterface
     */
    protected $request;

    /**
     * @Inject()
     * @var EventDispatcherInterface
     * */
    protected $eventDispatcher;

    public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
    {
        $this->container    = $container;
        $this->response     = $response;
        $this->request      = $request;
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $return = [
            'code'  => HttpStatus::HTTP_SUCCESS,
            'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_SUCCESS],
            'data'  => []
        ];
        try {
            $data   = $handler->handle($request)->getBody()->getContents();
            var_dump('这是打印开始');
            var_dump('这是初始数据');
            var_dump($data);
            if(self::isJson($data)){
                $data = json_decode($data, true);
            }
            var_dump('这是处理后的数据');
            var_dump($data);
            if (is_array($data)) {
                var_dump('is_array');
                if (!isset($data['code']) || !is_numeric($data['code'])) {
                    $return = [
                        'code'  => HttpStatus::HTTP_SUCCESS,
                        'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_SUCCESS],
                        'data' => $data
                    ];
                } else {
                    $return = $data;
                }
            } elseif (is_numeric($data)) {
                var_dump('is_numeric');
                if (isset(HttpStatus::HTTP_STATUS[$data])) {
                    $return = [
                        'code'  => $data,
                        'msg'   => HttpStatus::HTTP_STATUS[$data]
                    ];
                } else {
                    $return = [
                        'code'  => HttpStatus::HTTP_FAIL,
                        'msg'   => $data,
                        'data'  => []
                    ];
                }
            } elseif (is_string($data)) {
                var_dump('is_string');
                $return = [
                    'code'  => HttpStatus::HTTP_FAIL,
                    'msg'   => $data,
                    'data'  => []
                ];
            } elseif (is_null($data)) {
                var_dump('is_null');
                $return = [
                    'code'  => HttpStatus::HTTP_FAIL,
                    'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_FAIL],
                    'data'  => $data
                ];
            } elseif (is_object($data)) {
                var_dump('is_object');
                $data = json_decode(json_encode($data), true);
                $return = [
                    'code'  => HttpStatus::HTTP_SUCCESS,
                    'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_SUCCESS],
                    'data'  => $data
                ];
            } elseif (is_bool($data)) {
                var_dump('is_bool');
                $return = [
                    'code'  => $data ? HttpStatus::HTTP_SUCCESS : HttpStatus::HTTP_FAIL,
                    'msg'   => HttpStatus::HTTP_STATUS[$data ? HttpStatus::HTTP_SUCCESS : HttpStatus::HTTP_FAIL],
                    'data'  => $data
                ];
            }
        }catch (\Throwable $e){
            var_dump('Throwable');
            //  如果是数据校验错误
            if ($e instanceof ValidatorException) {
                $return = [
                    'code'  => HttpStatus::HTTP_FAIL,
                    'msg'   => $e->getMessage(),
                    'data'  => []
                ];
            } else {    //  系统抛出异常
                $return = [
                    'code'  => HttpStatus::HTTP_INTERNAL_SERVER_ERROR,
                    'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_INTERNAL_SERVER_ERROR],
                    'data'  => []
                ];
                $exception  = [
                    'line'  => $e->getLine(),
                    'file'  => $e->getFile(),
                    'code'  => $e->getCode(),
                    'msg'   => $e->getMessage(),
                    'trace' => $e->__toString(),
                    'user'  => $request->getUri()->getUserInfo(),
                    'data'  => $request->getUri()->getQuery(),
                    'url'   => $request->getUri()->getPath(),
                    'module'=> $request->getUri()->getPath(),
                    'method'=> $request->getMethod(),
                    'key'   => get_class($e)
                ];

//                $this->eventDispatcher->dispatch(new Exceptions($exception));//监听事件
//                $this->queueService->push($exception);
//                $this->otherQueueService->push($exception, 10);//自定义异步队列
                var_dump($exception);
                var_dump('exception end');
            }
        }catch (DbException $e){
            var_dump('DbException');
//            var_dump($e);
            $return = [
                'code'  => HttpStatus::HTTP_INTERNAL_SERVER_ERROR,
                'msg'   => HttpStatus::HTTP_STATUS[HttpStatus::HTTP_INTERNAL_SERVER_ERROR] . '!',
                'data'  => []
            ];
        }
//        var_dump($return);
        if (!empty($return)) return $this->response->json($return);
        return $handler->handle($request);
    }

    private static function isJson($data = '', $assoc = false){
        $data = json_decode($data, $assoc);
        if (($data && is_object($data)) || (is_array($data) && !empty($data))) {
            return $data;
        }
        return false;
    }
}